import {
  IsString,
  IsOptional,
  IsEnum,
  IsBoolean,
  IsDateString,
  MinLength,
  MaxLength,
  IsArray,
  ValidateNested,
  IsUUID,
  IsHexColor,
  IsInt,
  Min,
  Max
} from 'class-validator'
import { Transform, Type } from 'class-transformer'
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { PaginationDto } from './base.dto'
import { IsColor } from '../validators/custom.validators'

/**
 * 标签状态枚举
 */
export enum TagStatus {
  ACTIVE = 'active',
  INACTIVE = 'inactive'
}

/**
 * 标签类型枚举
 */
export enum TagType {
  GENERAL = 'general',
  CATEGORY = 'category',
  TECHNOLOGY = 'technology',
  TOPIC = 'topic',
  FEATURE = 'feature'
}

/**
 * 创建标签DTO
 */
export class CreateTagDto {
  @ApiProperty({ description: '标签名称', example: 'JavaScript' })
  @IsString({ message: '标签名称必须是字符串' })
  @MinLength(1, { message: '标签名称不能为空' })
  @MaxLength(50, { message: '标签名称不能超过50个字符' })
  @Transform(({ value }) => value?.trim())
  name: string

  @ApiProperty({ description: '标签别名（URL友好）', example: 'javascript' })
  @IsString({ message: '标签别名必须是字符串' })
  @MinLength(1, { message: '标签别名不能为空' })
  @MaxLength(50, { message: '标签别名不能超过50个字符' })
  @Transform(({ value }) =>
    value
      ?.toLowerCase()
      .trim()
      .replace(/[^a-z0-9-]/g, '-')
  )
  slug: string

  @ApiPropertyOptional({ description: '标签描述', example: 'JavaScript编程语言相关内容' })
  @IsOptional()
  @IsString({ message: '标签描述必须是字符串' })
  @MaxLength(500, { message: '标签描述不能超过500个字符' })
  @Transform(({ value }) => value?.trim())
  description?: string

  @ApiPropertyOptional({ description: '标签颜色', example: '#3498db' })
  @IsOptional()
  @IsColor({ message: '标签颜色格式不正确' })
  color?: string = '#3498db'

  @ApiPropertyOptional({ description: '标签图标', example: 'fab fa-js-square' })
  @IsOptional()
  @IsString({ message: '标签图标必须是字符串' })
  @MaxLength(100, { message: '标签图标不能超过100个字符' })
  @Transform(({ value }) => value?.trim())
  icon?: string

  @ApiPropertyOptional({ description: '标签类型', enum: TagType, example: TagType.TECHNOLOGY })
  @IsOptional()
  @IsEnum(TagType, { message: '标签类型不正确' })
  type?: TagType = TagType.GENERAL

  @ApiPropertyOptional({ description: '排序权重', example: 100 })
  @IsOptional()
  @IsInt({ message: '排序权重必须是整数' })
  @Min(0, { message: '排序权重不能小于0' })
  @Max(9999, { message: '排序权重不能大于9999' })
  @Transform(({ value }) => parseInt(value, 10))
  sortOrder?: number = 100

  @ApiPropertyOptional({ description: '是否在导航中显示', example: true })
  @IsOptional()
  @IsBoolean({ message: '是否在导航中显示必须是布尔值' })
  @Transform(({ value }) => value === 'true' || value === true)
  showInNav?: boolean = false

  @ApiPropertyOptional({ description: 'SEO关键词', example: 'javascript,编程,前端' })
  @IsOptional()
  @IsString({ message: 'SEO关键词必须是字符串' })
  @MaxLength(200, { message: 'SEO关键词不能超过200个字符' })
  @Transform(({ value }) => value?.trim())
  seoKeywords?: string

  @ApiPropertyOptional({ description: 'SEO描述', example: 'JavaScript编程语言学习资源和教程' })
  @IsOptional()
  @IsString({ message: 'SEO描述必须是字符串' })
  @MaxLength(300, { message: 'SEO描述不能超过300个字符' })
  @Transform(({ value }) => value?.trim())
  seoDescription?: string
}

/**
 * 更新标签DTO
 */
export class UpdateTagDto {
  @ApiPropertyOptional({ description: '标签名称', example: 'JavaScript' })
  @IsOptional()
  @IsString({ message: '标签名称必须是字符串' })
  @MinLength(1, { message: '标签名称不能为空' })
  @MaxLength(50, { message: '标签名称不能超过50个字符' })
  @Transform(({ value }) => value?.trim())
  name?: string

  @ApiPropertyOptional({ description: '标签别名（URL友好）', example: 'javascript' })
  @IsOptional()
  @IsString({ message: '标签别名必须是字符串' })
  @MinLength(1, { message: '标签别名不能为空' })
  @MaxLength(50, { message: '标签别名不能超过50个字符' })
  @Transform(({ value }) =>
    value
      ?.toLowerCase()
      .trim()
      .replace(/[^a-z0-9-]/g, '-')
  )
  slug?: string

  @ApiPropertyOptional({ description: '标签描述', example: 'JavaScript编程语言相关内容' })
  @IsOptional()
  @IsString({ message: '标签描述必须是字符串' })
  @MaxLength(500, { message: '标签描述不能超过500个字符' })
  @Transform(({ value }) => value?.trim())
  description?: string

  @ApiPropertyOptional({ description: '标签颜色', example: '#3498db' })
  @IsOptional()
  @IsColor({ message: '标签颜色格式不正确' })
  color?: string

  @ApiPropertyOptional({ description: '标签图标', example: 'fab fa-js-square' })
  @IsOptional()
  @IsString({ message: '标签图标必须是字符串' })
  @MaxLength(100, { message: '标签图标不能超过100个字符' })
  @Transform(({ value }) => value?.trim())
  icon?: string

  @ApiPropertyOptional({ description: '标签类型', enum: TagType, example: TagType.TECHNOLOGY })
  @IsOptional()
  @IsEnum(TagType, { message: '标签类型不正确' })
  type?: TagType

  @ApiPropertyOptional({ description: '标签状态', enum: TagStatus, example: TagStatus.ACTIVE })
  @IsOptional()
  @IsEnum(TagStatus, { message: '标签状态不正确' })
  status?: TagStatus

  @ApiPropertyOptional({ description: '排序权重', example: 100 })
  @IsOptional()
  @IsInt({ message: '排序权重必须是整数' })
  @Min(0, { message: '排序权重不能小于0' })
  @Max(9999, { message: '排序权重不能大于9999' })
  @Transform(({ value }) => parseInt(value, 10))
  sortOrder?: number

  @ApiPropertyOptional({ description: '是否在导航中显示', example: true })
  @IsOptional()
  @IsBoolean({ message: '是否在导航中显示必须是布尔值' })
  @Transform(({ value }) => value === 'true' || value === true)
  showInNav?: boolean

  @ApiPropertyOptional({ description: 'SEO关键词', example: 'javascript,编程,前端' })
  @IsOptional()
  @IsString({ message: 'SEO关键词必须是字符串' })
  @MaxLength(200, { message: 'SEO关键词不能超过200个字符' })
  @Transform(({ value }) => value?.trim())
  seoKeywords?: string

  @ApiPropertyOptional({ description: 'SEO描述', example: 'JavaScript编程语言学习资源和教程' })
  @IsOptional()
  @IsString({ message: 'SEO描述必须是字符串' })
  @MaxLength(300, { message: 'SEO描述不能超过300个字符' })
  @Transform(({ value }) => value?.trim())
  seoDescription?: string
}

/**
 * 标签查询DTO
 */
export class QueryTagDto extends PaginationDto {
  @ApiPropertyOptional({ description: '搜索关键词（标签名称、描述）', example: 'JavaScript' })
  @IsOptional()
  @IsString({ message: '搜索关键词必须是字符串' })
  @MaxLength(100, { message: '搜索关键词不能超过100个字符' })
  @Transform(({ value }) => value?.trim())
  search?: string = ''

  @ApiPropertyOptional({ description: '标签状态', enum: TagStatus, example: TagStatus.ACTIVE })
  @IsOptional()
  @IsEnum(TagStatus, { message: '标签状态不正确' })
  status?: TagStatus

  @ApiPropertyOptional({ description: '标签类型', enum: TagType, example: TagType.TECHNOLOGY })
  @IsOptional()
  @IsEnum(TagType, { message: '标签类型不正确' })
  type?: TagType

  @ApiPropertyOptional({ description: '是否在导航中显示', example: true })
  @IsOptional()
  @IsBoolean({ message: '是否在导航中显示必须是布尔值' })
  @Transform(({ value }) => value === 'true' || value === true)
  showInNav?: boolean

  @ApiPropertyOptional({ description: '最小文章数量', example: 1 })
  @IsOptional()
  @IsInt({ message: '最小文章数量必须是整数' })
  @Min(0, { message: '最小文章数量不能小于0' })
  @Transform(({ value }) => parseInt(value, 10))
  minArticleCount?: number

  @ApiPropertyOptional({ description: '创建开始日期', example: '2024-01-01' })
  @IsOptional()
  @IsDateString({}, { message: '创建开始日期格式不正确' })
  createdFrom?: string

  @ApiPropertyOptional({ description: '创建结束日期', example: '2024-12-31' })
  @IsOptional()
  @IsDateString({}, { message: '创建结束日期格式不正确' })
  createdTo?: string
}

/**
 * 标签响应DTO
 */
export class TagResponseDto {
  @ApiProperty({ description: '标签ID', example: 'uuid-123' })
  id: string

  @ApiProperty({ description: '标签名称', example: 'JavaScript' })
  name: string

  @ApiProperty({ description: '标签别名', example: 'javascript' })
  slug: string

  @ApiPropertyOptional({ description: '标签描述', example: 'JavaScript编程语言相关内容' })
  description?: string

  @ApiProperty({ description: '标签颜色', example: '#3498db' })
  color: string

  @ApiPropertyOptional({ description: '标签图标', example: 'fab fa-js-square' })
  icon?: string

  @ApiProperty({ description: '标签类型', enum: TagType, example: TagType.TECHNOLOGY })
  type: TagType

  @ApiProperty({ description: '标签状态', enum: TagStatus, example: TagStatus.ACTIVE })
  status: TagStatus

  @ApiProperty({ description: '排序权重', example: 100 })
  sortOrder: number

  @ApiProperty({ description: '是否在导航中显示', example: true })
  showInNav: boolean

  @ApiProperty({ description: '文章数量', example: 25 })
  articleCount: number

  @ApiProperty({ description: '使用次数', example: 150 })
  usageCount: number

  @ApiPropertyOptional({ description: 'SEO关键词', example: 'javascript,编程,前端' })
  seoKeywords?: string

  @ApiPropertyOptional({ description: 'SEO描述', example: 'JavaScript编程语言学习资源和教程' })
  seoDescription?: string

  @ApiPropertyOptional({ description: '创建者信息' })
  creator?: {
    id: string
    username: string
    realName?: string
  }

  @ApiPropertyOptional({ description: '最后更新者信息' })
  updater?: {
    id: string
    username: string
    realName?: string
  }

  @ApiProperty({ description: '创建时间', example: '2024-01-01T00:00:00.000Z' })
  createdAt: Date

  @ApiProperty({ description: '更新时间', example: '2024-01-01T00:00:00.000Z' })
  updatedAt: Date

  @ApiPropertyOptional({ description: '相关文章（最新5篇）' })
  recentArticles?: Array<{
    id: string
    title: string
    slug: string
    publishedAt?: Date
  }>
}

/**
 * 标签统计DTO
 */
export class TagStatsDto {
  @ApiProperty({ description: '总标签数', example: 100 })
  total: number

  @ApiProperty({ description: '活跃标签数', example: 85 })
  active: number

  @ApiProperty({ description: '非活跃标签数', example: 15 })
  inactive: number

  @ApiProperty({ description: '今日新增标签数', example: 3 })
  todayNew: number

  @ApiProperty({ description: '本月新增标签数', example: 20 })
  monthNew: number

  @ApiProperty({ description: '各状态标签数统计' })
  statusStats: Record<TagStatus, number>

  @ApiProperty({ description: '各类型标签数统计' })
  typeStats: Record<TagType, number>

  @ApiProperty({ description: '热门标签（按文章数）' })
  popularTags: Array<{
    id: string
    name: string
    slug: string
    color: string
    articleCount: number
  }>

  @ApiProperty({ description: '最新标签' })
  recentTags: Array<{
    id: string
    name: string
    slug: string
    color: string
    createdAt: Date
  }>

  @ApiProperty({ description: '未使用的标签' })
  unusedTags: Array<{
    id: string
    name: string
    slug: string
    createdAt: Date
  }>

  @ApiProperty({ description: '标签使用趋势（最近7天）' })
  usageTrend: Array<{
    date: string
    count: number
  }>
}

/**
 * 批量操作标签DTO
 */
export class BulkTagOperationDto {
  @ApiProperty({ description: '标签ID列表', example: ['uuid-1', 'uuid-2'] })
  @IsArray({ message: '标签ID列表必须是数组' })
  @IsUUID('4', { each: true, message: '标签ID格式不正确' })
  tagIds: string[]

  @ApiProperty({ description: '操作类型', enum: ['activate', 'deactivate', 'delete', 'merge'] })
  @IsEnum(['activate', 'deactivate', 'delete', 'merge'], { message: '操作类型不正确' })
  operation: 'activate' | 'deactivate' | 'delete' | 'merge'

  @ApiPropertyOptional({ description: '目标标签ID（合并操作时使用）', example: 'uuid-target' })
  @IsOptional()
  @IsUUID('4', { message: '目标标签ID格式不正确' })
  targetTagId?: string

  @ApiPropertyOptional({ description: '操作原因', example: '批量清理无用标签' })
  @IsOptional()
  @IsString({ message: '操作原因必须是字符串' })
  @MaxLength(500, { message: '操作原因不能超过500个字符' })
  reason?: string
}

/**
 * 标签排序DTO
 */
export class SortTagDto {
  @ApiProperty({ description: '标签排序列表', type: [Object] })
  @IsArray({ message: '标签排序列表必须是数组' })
  @ValidateNested({ each: true })
  @Type(() => TagSortItem)
  tags: TagSortItem[]
}

/**
 * 标签排序项DTO
 */
export class TagSortItem {
  @ApiProperty({ description: '标签ID', example: 'uuid-123' })
  @IsUUID('4', { message: '标签ID格式不正确' })
  id: string

  @ApiProperty({ description: '排序权重', example: 100 })
  @IsInt({ message: '排序权重必须是整数' })
  @Min(0, { message: '排序权重不能小于0' })
  @Max(9999, { message: '排序权重不能大于9999' })
  sortOrder: number
}

/**
 * 标签合并DTO
 */
export class MergeTagDto {
  @ApiProperty({ description: '源标签ID列表', example: ['uuid-1', 'uuid-2'] })
  @IsArray({ message: '源标签ID列表必须是数组' })
  @IsUUID('4', { each: true, message: '源标签ID格式不正确' })
  sourceTagIds: string[]

  @ApiProperty({ description: '目标标签ID', example: 'uuid-target' })
  @IsUUID('4', { message: '目标标签ID格式不正确' })
  targetTagId: string

  @ApiPropertyOptional({ description: '是否删除源标签', example: true })
  @IsOptional()
  @IsBoolean({ message: '是否删除源标签必须是布尔值' })
  @Transform(({ value }) => value === 'true' || value === true)
  deleteSourceTags?: boolean = true

  @ApiPropertyOptional({ description: '合并原因', example: '标签重复，进行合并' })
  @IsOptional()
  @IsString({ message: '合并原因必须是字符串' })
  @MaxLength(500, { message: '合并原因不能超过500个字符' })
  reason?: string
}

/**
 * 标签导入DTO
 */
export class ImportTagDto {
  @ApiProperty({ description: '标签数据列表', type: [CreateTagDto] })
  @IsArray({ message: '标签数据列表必须是数组' })
  @ValidateNested({ each: true })
  @Type(() => CreateTagDto)
  tags: CreateTagDto[]

  @ApiPropertyOptional({ description: '是否覆盖已存在的标签', example: false })
  @IsOptional()
  @IsBoolean({ message: '是否覆盖已存在的标签必须是布尔值' })
  @Transform(({ value }) => value === 'true' || value === true)
  overwrite?: boolean = false

  @ApiPropertyOptional({ description: '导入模式', enum: ['create', 'update', 'upsert'] })
  @IsOptional()
  @IsEnum(['create', 'update', 'upsert'], { message: '导入模式不正确' })
  mode?: 'create' | 'update' | 'upsert' = 'create'
}
